#include "ServerController.h"

#include <boost/bind.hpp>
#include "../../../domain/configuration/NetworkConfiguration.h"
#include "../../../domain/helpers/CardsDealer.h"
#include "../../../domain/helpers/NetworkException.h"
#include "../../../views/models/network/CardSetViewModel.h"
#include "../../../views/concrete/remote/AccusationView.h"
#include "../../../views/concrete/graphic/BoardView.h"
#include "../../../views/concrete/graphic/DeductionView.h"
#include "../../../views/concrete/server/AccusationView.h"
#include "../../../views/concrete/server/BoardView.h"
#include "../../../views/concrete/server/DeductionView.h"
#include "../../../views/concrete/server/GameplayView.h"

using namespace Controllers;

ServerController::ServerController(Utils::GUI::Form* form)
	: GameplayController(form)
{
	server = new Domain::Network::GameServer();
	view = new Views::Server::GameplayView(form, server);
}

void ServerController::startGame()
{
	server->serve();
	GameplayController::startGame();
}

TurnController* ServerController::createTurnController()
{
	AccusationController* accusation_controller = new AccusationController(new Views::Server::AccusationView(server, form, server_owner, current_player),
			logger, current_player, cards, searched_cards);
	BoardController* board_controller = new BoardController(new Views::Server::BoardView(server, form, server_owner, current_player),
			logger, current_player, cards.getRoomsCards());
	DeductionController* deduction_controller = new DeductionController(new Views::Server::DeductionView(form, server, server_owner, cards),
			logger, current_player, players, cards);
	return new TurnController(accusation_controller, board_controller, deduction_controller);
}

Players::Player* ServerController::createPlayer(Cards::PlayerCard* card, Players::PLAYER_TYPE type)
{
	Players::Player* player = GameplayController::createPlayer(card, type);
	if (type == Players::LOCAL)
	{
		server_owner = player;
		server->player_owner = new Domain::Network::PlayerClient(0, player);
	}
	if (type == Players::REMOTE)
	{
		for (Domain::Network::GameServer::GameClients::iterator i = server->game_clients.begin();
			i != server->game_clients.end(); ++i)
		{
			if (!(*i)->hasPlayerSet())
			{
				(*i)->setPlayer(player);
				break;
			}
		}
	}
#ifdef _DEBUG
	std::clog << static_cast<std::string>(player->getName()) << " " << type << std::endl;
#endif
	return player;
}

void ServerController::dealCards()
{
	searched_cards = Domain::Helpers::CardsDealer(players, cards).deal();
	sf::Packet packet;
	Views::Models::Network::CardSetViewModel csvm(searched_cards);
	packet << csvm;

	for (int i = players.size(); i > 0; --i)
	{
		Players::Player* p = players.front();
		players.pop();
		csvm.card_set = p->getCards();
		packet << csvm;
		players.push(p);
	}
	server->sendToAll(Domain::Configuration::Network::GAMEPLAY_CARDS, packet);
	cardsDealEvent();
}

void ServerController::endGame(Domain::Configuration::GAME_END_REASON reason)
{
	if (winner == server_owner)
	{
		gameWonEvent(winner, searched_cards, reason);
	}
	else
	{
		gameLostEvent(winner, searched_cards, reason);
	}
}

